package edu.neepu;

/**
 * Thread Pool
 */
public class DownloadPool {
    private static final int THREAD_NUM = 5; //thread pool capacity

    private int poolSize; //the size of thread pool
    private Thread[] threads; //thread array
    private final Object threadLock; //thread array lock

    //singleton
    private static DownloadPool pool;

    public static synchronized DownloadPool getPool() {
        if (pool == null) {
            pool = new DownloadPool(THREAD_NUM);
        }
        return pool;
    }

    private DownloadPool(int size) {
        this.poolSize = size;
        this.threads = new Thread[size];
        this.threadLock = new Object();
    }

    /**
     * Get whether can download.
     * @return true: can download. false: otherwise.
     */
    public boolean canDownload() {
        synchronized (this.threadLock) {
            //遍历线程数组
            for (int i=0; i<this.poolSize; i++) {
                if (this.threads[i] == null) {
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * Start the download
     * @param urlSegment
     * @param bookName
     * @param chapName
     * @param count four params used in GetText spider. See @GetText.getBookText
     * @return true: success. false: failed.
     */
    public boolean startDownload(String urlSegment, String bookName, String chapName, int count) {
        while (!this.canDownload()) {
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Thread th;
        synchronized (this.threadLock) {
            //查找当前空的位置
            int index = -1;
            for (int i=0; i<this.poolSize; i++) {
                if (this.threads[i] == null) {
                    index = i;
                    break;
                }
            }
            //创建爬虫
            Spider getText = new GetText(urlSegment, bookName, chapName, count);
            th = new Downloader(getText, index);
            this.threads[index] = th;
        }
        th.start();
        return true;
    }

    /**
     * Wait for all threads stop
     */
    public void waitUntilStop() {
        while (true) {
            //获取一个没有结束的线程
            Thread th = null;
            synchronized (this.threadLock) {
                for (int i=0; i<this.poolSize; i++) {
                    if (this.threads[i] != null) {
                        th = this.threads[i];
                        break;
                    }
                }
            }
            if (th == null) break;
            try {
                //尝试等待线程结束
                th.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Downloader Thread
     */
    private class Downloader extends Thread{
        private Spider spider; //the spider instance
        private int index; //current index in thread array

        public Downloader(Spider spider, int index) {
            this.spider = spider;
            this.index = index;
        }

        public void run() {
            if (this.spider == null) return;
            try {
                //make the spider crawl!
                spider.getText();
            } catch (Exception e) {
                e.printStackTrace();
            }
            //delete this thread from the thread array
            synchronized(threadLock) {
                threads[this.index] = null;
            }
        }

    }

}
